#!/usr/bin/env python
# coding: utf-8


############################################################################
#                   2012/05/29  Ver 1.8                                    #
#Release note:                                                             #
#1、Shen Yibo find when use the sript to download version to 13,           #
#   the ne's start filesys have not change, resolved the problem.          #
#2、More NE to ftp file at the same time, it will be failed, one variables #
#   must be reinitialized.                                                 #
#3、modify the pos restart flow post by Xiaodong Li                        #
#4、For the pos slot,if slot = 0,the script notice "invalid slot", not"skip#
#   and move the next"                                                     #
#5、Modify the menu information by the new upgrade flow revise             #
#6、Fixed the bug                                                          #
#7、Add the version check selection                                        #
#                   2012/07/11  Ver 1.9                                    #
#8、Modify the version check, N64F01 and N64F01(C0)                        #
############################################################################
#                   2012/08/15  Ver 1.12                                   #
#11、Add auto creat the /tffs/sys and /fs2/sys                             #
#12、Add a selection for ingnore lsp errlog = 19 in sync check             #
############################################################################


import re
import os
from copy import deepcopy
import time

from onshs.ne.tnxxx.tnxxxcfg_basecase import *

ramdisk_dir = "/ramdisk:0/upgrade"
tffs_dir = "/tffs/sys"
boot_dir = "/ramdisk:0"

log_check_version_fail = "Slot:%s Card:%s check version %s current version:%s dest version:%s fail!\n"
log_check_version_success = "Slot:%s Card:%s check version %s current version:%s dest version:%s success!\n"

version_soft_dic ={
    0:"BIOS",
    1:"BSP",
    2:"SoftWare",
}

version_hard_dic = {
    0:"CPLD",
    1:"FPGA1",
    2:"FPGA2",
}

def line():
    try:
        raise Exception
    except:
        return sys.exc_info()[2].tb_frame.f_back.f_lineno
         
           
class SbbUpgradeDowngradeSoftware(TnxxxCfg_BaseCase) :
    def _parse_local_file(self, put_file_list):
        for put_file in put_file_list:
            if list != type(put_file) or \
               3 != len(put_file) or \
               str != type(put_file[0]) or \
               str != type(put_file[1]) or \
               str != type(put_file[2]):
                self.logger.error(str(line())+" _parse_local_file : param type error <%s>"%(str(put_file)))
                return False
            put_file_original = deepcopy(put_file)
            put_file[2] = self._parse_last_file_name(put_file[1], put_file[2])
            if not os.path.isfile(self._parse_dir_name(put_file[1])+put_file[2]):
                self.info_show(self.log_node_fail, self.log_file_not_existed%(self._parse_dir_name(put_file[1])+put_file[2]))                
                return False            
        return True
    
    def _put_file(self, dst_dir, src_dir, file_name, slot_list, active_oam_slot):
        cmd_list = [
            "cd %s"%(dst_dir),
            "put %s %s"%(self._parse_dir_name(src_dir)+file_name,file_name),
        ]
        cmd_info_list = [
            [cmd_list, {}, 0, FTP_PORT],
        ]
        
        for slot in slot_list:
            #active opca
            if slot == active_oam_slot:
                if not self.run(cmd_info_list):
                    self.info_show(self.log_node_fail, "The active opca ftp files now\n" + self.log_put_fail%(self.get_ne_ip(0),dst_dir,str(slot),dst_dir+'/'+file_name))
                    return False
                else:
                    self.info_show(self.log_node_success, "The active opca ftp files now\n" + self.log_put_success%(self.get_ne_ip(0),dst_dir,str(slot),dst_dir+'/'+file_name))
            
            #从active的OPCA中取最新的文件传输到对应的槽位    
            else:
                active_backupsys = self.slot_backupsys_list[0][1]
                cmd_put = '$.necli.0.CmdEx "PutFile",{{String,"192.168.210.%d"},{String,"weihu"},{String,"cjhyy300"},{String,"%s"},{String,"%s"},{String,"%s/%s"}}}'\
                      %(slot, dst_dir, file_name, active_backupsys, file_name)                
                if not self.tnxxx.send(cmd_put, "putfile ret = 1", self.get_ne_ip(0), 0, MTN_PORT, 600):                
                    self.info_show(self.log_node_fail, "The standby opca and pos ftp files now\n" + self.log_put_fail%(self.get_ne_ip(0),dst_dir,str(slot),dst_dir+'/'+file_name))
                    return False
                else:
                    self.info_show(self.log_node_success, "The standby opca and pos ftp files now\n" + self.log_put_success%(self.get_ne_ip(0),dst_dir,str(slot),dst_dir+'/'+file_name))
        return True
        
    def _parse_dir_name(self, dir_name):
        if None == re.search(r"[\\|/]$", dir_name):
            dir_name += '/'
        return dir_name
    
    def _parse_last_file_name(self, path, src_name):
        """
        分析path中符合name的最新目录或者文件
        成功返回最新的名字，失败返回""
        """    
        if not os.path.exists(path):
            self.logger.info(str(line())+" _parse_last_file_name : dir %s not exist"%(path))
            return ""
        
        if src_name.find(r"(\d+)") >= 0:
            base = 10
        elif src_name.find(r"([\da-f]+)") >= 0:
            base = 16
        else:
            return src_name
            
        last_version = 0
        last_file_name = ""
        try:
            name_list = os.listdir(path)
            for name in name_list:
                m = re.match(src_name, name, re.I)
                if None == m:
                    continue
                version = int(m.group(1), base)
                if version >= last_version:
                    last_version = version
                    last_file_name = name
            rtn = last_file_name
        except:
            self.logger.error(str(line())+" _parse_last_file_name : failed "+path+" "+src_name)
            rtn = ""
        return rtn
    
    def put_files(self, put_file_list, slot_list, active_oam_slot):
        """
        put_file_list = [put_file(list),...]
        put_file = [dst_dir, src_dir, src_name]
            dst_dir(str)    --目的目录
            src_dir(str)    --源目录
            src_name(str)   --文件名, 包括"(\d+)或者([\da-f]+)"的表示最新版本
        """   
        if list != type(put_file_list):
            self.logger.error(str(line())+" put_files : param type error")
            return False
        #检查本地文件是否存在
        if not self._parse_local_file(put_file_list):
            return False
        #上传文件到网元
        for put_file in put_file_list:
            if not self._put_file(put_file[0], put_file[1], put_file[2], slot_list, active_oam_slot):
                return False            
        return True
    
    def _md5_file(self, dst_dir, file_name, file_md5, slot_list, active_oam_slot): 
        for slot in slot_list:
            #active opca
            if slot == active_oam_slot:
                slot = 0
            
            rtn = self.tnxxx.send_rtn_str('upgrade_script_md5=0', self.get_ne_ip(0), slot, DEV_PORT)
            rtn = self.tnxxx.send_rtn_str('sp _ZN7NSPFile3MD5EPcRS0_h,0,"%s",&upgrade_script_md5,0'%(dst_dir+'/'+file_name), self.get_ne_ip(0), slot, DEV_PORT)
            
            i = 0;
            while i < 30:
                i = i + 1
                time.sleep(2)
                
                rtn = self.tnxxx.send_rtn_str('strcmp("%s",upgrade_script_md5)'%(file_md5), self.get_ne_ip(0), slot, DEV_PORT)
                if [] != re.findall("value = 0",rtn):  
                    self.info_show(self.log_node_operation, self.log_md5_success%(self.get_ne_ip(0),slot,file_name))
                    break
                    

            else:
                self.info_show(self.log_node_fail, self.log_md5_fail%(self.get_ne_ip(0),slot,file_name))
                return False
                
                
        return True
    
    def md5_files(self, put_file_list, slot_list, active_oam_slot):
        """
        put_file_list = [put_file(list),...]
        put_file = [dst_dir, src_dir, src_name, md5]
            dst_dir(str)    --目的目录
            src_dir(str)    --源目录
            src_name(str)   --文件名, 包括"(\d+)或者([\da-f]+)"的表示最新版本
            md5(str)        --文件的md5值
        """   
        if list != type(put_file_list):
            self.logger.error(str(line())+" md5_files : param type error")
            return False        
        
        for md5_file in put_file_list:
            if not self._md5_file(md5_file[0], md5_file[2], md5_file[3], slot_list, active_oam_slot):
                return False            
        return True  
###########################################################################################################
    def copy_files(self, copy_file_list, slot):
        """
        copy_file_list = [copy_file(list),...]
        copy_file = [dst_dir, dst_name, src_dir, src_name]
            dst_dir         --目的目录
            dst_name        --目的文件名
            src_dir         --源目录
            src_name        --源文件名, 包括"(\d+)或者([\da-f]+)"的表示最新版本
        """
        if list != type(copy_file_list):
            self.logger.error(str(line())+" copy_files : param type error")
            return False
        for copy_file in copy_file_list:
            if list != type(copy_file) or \
               4 != len(copy_file) or \
               str != type(copy_file[0]) or \
               str != type(copy_file[1]) or \
               str != type(copy_file[2]) or \
               str != type(copy_file[3]):
                self.logger.error(str(line())+" copy_files : copy_file type error <%s>"%(str(copy_file)))
                return False
            if copy_file[3].find(r"(\d+)") >= 0 or copy_file[3].find(r"([\da-f]+)") >= 0:
                rtn = self.tnxxx.send_rtn_str('ll "%s"'%(copy_file[2]), self.get_ne_ip(0), slot, DEV_PORT)
                s = re.search(copy_file[3], rtn, re.I)
                if None == s:
                    self.logger.error(str(line())+" copy_files : file not exist"%(str(copy_file)))
                    return False
                copy_file[1] = copy_file[3] = s.group(0)
            cmd_copy = 'copy "%s/%s","%s/%s"'%(copy_file[2],copy_file[3],copy_file[0],copy_file[1])
            if not self.tnxxx.send(cmd_copy, "value = 0 = 0x0", self.get_ne_ip(0), slot, DEV_PORT, 600):
                self.logger.error(str(line())+" copy_files : cmd <%s> failed"%(cmd_copy))
                return False
        return True
###########################################################################################################
    def _parse_ne_file(self, delete_file_list, slot):
        delete_file_list_original = deepcopy(delete_file_list)
        while 0 < len(delete_file_list):
            delete_file_list.pop()         
        for delete_file in delete_file_list_original:
            if list != type(delete_file) or \
               2 != len(delete_file) or \
               str != type(delete_file[0]) or \
               str != type(delete_file[1]):
                self.logger.error(str(line())+" _parse_ne_file : param type error <%s>"%(str(delete_file)))
                return False
            delete_file_original = deepcopy(delete_file)
            rtn = self.tnxxx.send_rtn_str('ll "%s"'%(delete_file[0]), self.get_ne_ip(0), slot, DEV_PORT)
            file_name_list = re.findall(r"\d\d:?\d\d\s+([\w._]+)[^/]\s+$",rtn,re.M) #同时支持两种形式 xx:xx 文件名 和 xxxx 文件名
            is_file_exist = False
            for file_name in file_name_list:
                if ".+" == delete_file[1]:
                    delete_file_list.append([delete_file[0], file_name])
                    is_file_exist = True
                elif delete_file[1].find(r"(\d+)") >= 0 or delete_file[1].find(r"([\da-f]+)") >= 0:
                    if re.match(delete_file[1], file_name, re.I):
                        delete_file_list.append([delete_file[0], file_name])
                        is_file_exist = True
                        break
                elif file_name.lower() == delete_file[1].lower():
                    delete_file_list.append([delete_file[0], file_name])
                    is_file_exist = True
                    break
            #if not is_file_exist:
                #self.logger.info(str(line())+" _parse_ne_file : file not exist <%s>"%(str(delete_file_original)))            
        return True
    
    def _delete_file(self, dir_name, file_name, slot):
        cmd_delete = 'remove "%s/%s"'%(dir_name, file_name)
        return self.tnxxx.send(cmd_delete, "value = 0 = 0x0", self.get_ne_ip(0), slot, DEV_PORT)
        
    def delete_files(self, delete_file_list, slot):
        """
        delete_file_list = [delete_file(list),...]
        delete_file = [dir_name, file_name]
            dir_name(str)   --目录
            file_name(str)  --文件名,".+"表示整个目录 包括"(\d+)或者([\da-f]+)"的表示最新版本
        """
        if list != type(delete_file_list):
            self.logger.error(str(line())+" delete_files : param type error")
            return False
                   
        #检查网元文件是否存在
        if not self._parse_ne_file(delete_file_list, slot):
            return False
        #删除网元的文件
        for delete_file in delete_file_list:
            if not self._delete_file(delete_file[0], delete_file[1], slot):
                self.info_show(self.log_node_fail, self.log_delete_fail%(self.get_ne_ip(0),slot,delete_file[0]+delete_file[1]))
                return False
            else:
                self.info_show(self.log_node_operation, self.log_delete_success%(self.get_ne_ip(0),slot,delete_file[0]+delete_file[1]))
        return True 
           

    #############################################################################################
    #                                                                                           #
    #                                    查询网元当前安装的板卡                                 #
    #                                                                                           #
    #############################################################################################
    def check_card_install(self):
        card_info_list = []
        card_attention_list = [1,2,3,4,5,6,7,8]
        card_tpye_list = ["OPCA","N64F01","N16F01","CM48E16","CM48E16S","CGF12", "CGF12S"]
        restart_slot_dic = {}
        
        cmd = r"show card"            
        rtn = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), 0, CLI_PORT)
        
        card_info_list = re.findall(r"slot:\s+(\d+)\s+(?:--More--\s+)?stat:\s+\w+\s+(?:--More--\s+)?Card:\s+(\w+)\s+", rtn, re.I)
        for card_info in card_info_list:
            #关注1，2，3，4，5，6，7，8槽位的复位
            if int(card_info[0]) in card_attention_list:
                card_name = card_info[1].upper()
                card_slot = int(card_info[0])
                #只关注单板"OPCA","N64F01","N16F01","CM48E16"
                if card_name in card_tpye_list:
                    if not restart_slot_dic.has_key(card_name):
                        restart_slot_dic[card_name] = []
                    restart_slot_dic[card_name].append(card_slot)
        return restart_slot_dic
    
    #############################################################################################
    #                                                                                           #
    #                                    查询两块OPCA的备用文件目录                             #
    #                                                                                           #
    #############################################################################################
    
    def get_slot_backupsys_list(self, ip):
        """
        return slot_backupsys_list.
        slot_backupsys_list = [slot, backupsys]            
                slot(int)         --槽位号
                backupsys(str) --backup的文件启动系统
                slot_backupsys_list[0]存放的是主OPCA的信息
        """
        slot_backupsys_list = []
        query_backupsys_cmd = '''$.dbgcli.0.Cmd "queryasyn valid 1, FtamStatus, (CurBootSys,Fid), *"'''
        query_masterppc_cmd = '''$.dbgcli.0.Cmd "queryasyn valid 1, NeStat, (MasterPPC), *"'''
        #$.dbgcli.0.Cmd "queryasyn valid 1, FtamStatus, (CurBootSys), Fid='\a=0\s=4\c=1'"
        #$.dbgcli.0.Cmd "queryasyn valid 1, NeStat, (MasterPPC), *"        
        
        #get masterppc
        rtn_str = None
        rtn_str = self.tnxxx.send_rtn_str(query_masterppc_cmd, ip, 0, MTN_PORT)
        #有可能出现rtn_str无返回值的情况
        if [] == re.findall('success', rtn_str):         
            self.info_show(self.log_node_fail, self.log_connect_fail%(ip))
            return slot_backupsys_list
        else:
            if [] == re.findall('\d',rtn_str):
                self.info_show(self.log_node_fail, self.log_connect_fail%(ip))
                return slot_backupsys_list                
            else:
                masterppc = int(re.findall('\d',rtn_str)[0])
        
        #get masterppc and slaveppc(if it is existed)'s backup boot sys
        rtn_str = None
        rtn_str = self.tnxxx.send_rtn_str(query_backupsys_cmd, ip, 0, MTN_PORT)
        if [] == re.findall('success', rtn_str):         
            self.info_show(self.log_node_fail, self.log_connect_fail%(ip))
            return slot_backupsys_list
        else:
            field_list = re.findall('{\r\n.+\r\n}',rtn_str)
            curbootsys_list=re.findall('\d',field_list[0])
            fid_list=re.findall('s=\d',field_list[1])
            
        for i,element in enumerate(curbootsys_list):
            if 1 == int(curbootsys_list[i]):
                backupsys="/fs2/sys"
            else:
                backupsys="/tffs/sys"
            slot = int(fid_list[i][2:])
            slot_backupsys_element=[slot,backupsys]
            if masterppc == slot:
                slot_backupsys_list.insert(0,slot_backupsys_element)
                #提示主备板槽位和系统目录的信息
                self.info_show(self.log_node_success, "Get the Active opca slot:%d, backsys:%s" % (slot, backupsys))
            else:
                slot_backupsys_list.append(slot_backupsys_element)
                self.info_show(self.log_node_success, "Get the Standby opca slot:%d, backsys:%s" % (slot, backupsys))
        return slot_backupsys_list        
       

    #############################################################################################
    #                                                                                           #
    #                                    网元同步校验                                           #
    #                                                                                           #
    #############################################################################################
    
    #查找指定槽位列表的单板类型是否存在
    def get_slot_cardtype_list(self, slot_list,card_type):
        rtn = None
        rtn = self.tnxxx.send_rtn_str("show card", self.get_ne_ip(0), 0, CLI_PORT)
        card_info_list = re.findall(r"slot:\s+(\d+)\s+(?:--More--\s+)?stat:\s+\w+\s+(?:--More--\s+)?Card:\s+(\w+)\s+", rtn, re.I)
        slot_cardtype_list = []
        for card_info in card_info_list:
            slot = int(card_info[0])
            if slot not in slot_list:
                continue
            
            card_name = card_info[1].upper()
            if card_name != card_type:
                continue
            
            slot_cardtype_list.append(slot)
            
        return slot_cardtype_list
        
    def get_master_opca(self):
        query_masterppc_cmd = '''$.dbgcli.0.Cmd "queryasyn valid 1, NeStat, (MasterPPC), *"'''
        rtn_str = None        
        rtn_str = self.tnxxx.send_rtn_str(query_masterppc_cmd, self.get_ne_ip(0), 0, MTN_PORT)
        if [] == re.findall('success', rtn_str) or [] == re.findall('\d',rtn_str):         
            self.info_show(self.log_node_fail, self.log_master_opca_fail%(self.get_ne_ip(0)))
            return False
        else:            
            self.master_opca = int(re.findall('\d',rtn_str)[0])
            self.slave_opca = 7 - self.master_opca
            self.info_show(self.log_node_success, self.log_master_opca_success%(self.get_ne_ip(0),self.master_opca))           
            return True 
    
    def check_hw(self):
        query_cmd_list = [['$.card.%d.mtn.0.cmds "checkhw"'%(self.master_opca),self.master_opca],['$.card.%d.mtn.0.cmds "checkhw"'%(self.slave_opca),self.slave_opca]]
        
        #保存errlog的列表
        lspid_errlog_list = []
        
        for query_cmd in query_cmd_list:
            rtn_str = None       
            rtn_str = self.tnxxx.send_rtn_str(query_cmd[0], self.get_ne_ip(0), query_cmd[1], MTN_PORT)
            if [] == re.findall('success', rtn_str):         
                self.info_show(self.log_node_fail, self.log_checkhw_fail%(self.get_ne_ip(0),query_cmd[1]))
                return False
            elif [] == re.findall('lsp hw data is ok', rtn_str):
                #针对LSP 的errlog = 19进行特殊处理,只要存在一个不是19的errlog，就返回失败，否则返回成功，忽略19的errlog
                lspid_errlog_list = re.findall('.lspid=(\d+).\s+.errLog=(\d+).', rtn_str)
                
                if lspid_errlog_list !=[]:
                    for lspid_errlog in lspid_errlog_list:
                        if  int(lspid_errlog[1]) != 19:
                            self.info_show(self.log_node_fail, self.log_checkhw_lsp_fail%(self.get_ne_ip(0),query_cmd[1]))
                            return False
                        else:
                            #如果全部是errlog = 19则进行选择，否则保持以前
                            #可以考虑是用户输入选择
                            print "Next hop ip address of lspid:%s is unsynced.\n"%lspid_errlog[0] 
                   
                    note = "Would you like to ingore next hop ip address unsync? ( y: yes, n: no)\nInput < y or n > :\nplease input:"
                    proceed = self.get_the_customer_input(note)
                    
                    #如果选择处理，则失败返回，直接进行下一次校验，否则继续剩下的校验
                    if proceed == "N":
                        return False
                        
            elif [] == re.findall('pw hw data is ok', rtn_str):
                self.info_show(self.log_node_fail, self.log_checkhw_pw_fail%(self.get_ne_ip(0),query_cmd[1]))
                return False
            elif [] == re.findall('eth pw hw data is ok', rtn_str):
                self.info_show(self.log_node_fail, self.log_checkhw_ethpw_fail%(self.get_ne_ip(0),query_cmd[1]))
                return False
            else:
                self.info_show(self.log_node_success, self.log_checkhw_success%(self.get_ne_ip(0),query_cmd[1]))
            
        return True
    
    def check_unit_port_link(self):
        cmd_list = [['dbg_if_print',self.master_opca],['dbg_if_print',self.slave_opca]]
        
        opca_linkup_portlist = [] 
        for cmd in cmd_list:
            rtn_str = None
            linkup_port_list = []
            rtn_str = self.tnxxx.send_rtn_str(cmd[0], self.get_ne_ip(0), cmd[1], DEV_PORT)            
            linkup_port_list = re.findall(r"\s+(\d+)\s+(\d+)\s+(\w+)\(up\/up\)", rtn_str)
            opca_linkup_portlist.append(linkup_port_list)
        
        if len(opca_linkup_portlist[0]) != len(opca_linkup_portlist[1]):
            self.info_show(self.log_node_fail, self.log_check_linkstatus_fail%(self.get_ne_ip(0),"all","all"))
            return False
        
        #linkup_port_list = [[unit,port,ge0],[unit,port,ge1],...]   
        for i in range(0,len(opca_linkup_portlist[0])):
            if opca_linkup_portlist[0][i][0] == opca_linkup_portlist[1][i][0] and opca_linkup_portlist[0][i][1] == opca_linkup_portlist[1][i][1] and opca_linkup_portlist[0][i][2] == opca_linkup_portlist[1][i][2]:                
                continue
            else:
                self.info_show(self.log_node_fail, self.log_check_linkstatus_fail%(self.get_ne_ip(0),opca_linkup_portlist[0][i][0],opca_linkup_portlist[0][i][1]))
                return False
        self.linkup_portlist = opca_linkup_portlist[0]
        self.info_show(self.log_node_success, self.log_check_linkstatus_success%(self.get_ne_ip(0)))    
           
        return True
    
    def check_phy_status(self):
        cmd_list = [['dbg_print_master_phy_stat',self.master_opca],['dbg_print_slave_phy_stat',self.slave_opca]]
        
        for element in self.linkup_portlist:
            opca_phy_status_list = []
            for cmd in cmd_list:
                rtn_str = None
                phy_status_list = []
                
                rtn_str = self.tnxxx.send_rtn_str(cmd[0]+r' '+element[0]+r','+element[1], self.get_ne_ip(0), cmd[1], DEV_PORT)            
                phy_status_list = re.findall(r"\s+(\w+)\s+:\s+(\d+)", rtn_str)
                opca_phy_status_list.append(phy_status_list)
            
            if len(opca_phy_status_list[0]) != len(opca_phy_status_list[1]):
                self.info_show(self.log_node_fail, self.log_check_phystatus_fail%(self.get_ne_ip(0),"all","all"))
                return False 
                
            for i in range(0,len(opca_phy_status_list[0])):
                if opca_phy_status_list[0][i][0] == opca_phy_status_list[1][i][0] and opca_phy_status_list[0][i][1] == opca_phy_status_list[1][i][1]:
                    continue
                else:
                    self.info_show(self.log_node_fail, self.log_check_phystatus_fail%(self.get_ne_ip(0),element[0],element[1]))
                    return False
        
        self.info_show(self.log_node_success, self.log_check_phystatus_success%(self.get_ne_ip(0)))      
        return True
    
    def check_nms_sync(self):
        cmd = r'show opca synchronization-status'
        
        rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), 0, CLI_PORT)
        
        if None == re.search("not synchronized", rtn, 0):
            self.info_show(self.log_node_success, self.log_check_nms_sync_success%(self.get_ne_ip(0)))
            return True
        else:
            self.info_show(self.log_node_fail, self.log_check_nms_sync_fail%(self.get_ne_ip(0)))
            return False
        
    #返回True代表网元同步，严格校验有两块OPCA，其他情况都是失败
    def check_ne_sync(self):        
        self.master_opca = 0
        self.slave_opca = 0
        self.linkup_portlist = []
        self.tnxxx.disconnect()
        
        slot_list = self.get_slot_cardtype_list([3,4],"OPCA")
        
        if len(slot_list) == 0:
            self.info_show(self.log_node_fail, "slot_list  =  0" + self.log_opca_slotlist_fail%(self.get_ne_ip(0)))
            return False
        elif len(slot_list) == 1:
            self.info_show(self.log_node_fail, "slot_list  =  1" + self.log_opca_slotlist_fail%(self.get_ne_ip(0)))
            return False
        if False == self.get_master_opca():
            return False
        if False == self.check_hw():
            return False    
        if False == self.check_unit_port_link():
            return False
        if False == self.check_phy_status():
            return False
        if False == self.check_nms_sync():
            return False
        
        self.info_show(self.log_node_success, self.log_sync_status_success%(self.get_ne_ip(0)))
        return True
    
    #############################################################################################
    #                                                                                           #
    #                                    烧写CPLD和BIOS实现                                     #
    #                                                                                           #
    #############################################################################################
    #烧写CPLD的函数
    def _bsp_jtag_download_cpld_file(self, dst_dir, src_dir, file_name, slot_list):
        rtn_list = []
        for slot in slot_list:
            #如果是OPCA，就不进行烧写的操作
            if slot == 3 or slot == 4:
                continue
            else:
                if(self.cpld == "True"):
                    cmd = r'bsp_jtag_download "%s"' % (dst_dir + r'/' + file_name)
                    rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), slot, DEV_PORT)
                    time.sleep(180)
                
                """
                #remove from here , at last have a version check
                #获取0x4,0x5（CPLD版本）寄存器的值
                rtn = self.tnxxx.send_rtn_str("*(0xa0000000+0x4*4)&0xff", self.get_ne_ip(0), slot, DEV_PORT)                       
                rtn_str = None
                rtn_str = re.search(r'= \d+',rtn)
                if None == rtn_str:
                    self.info_show(self.log_node_fail, self.log_connect_slot_fail%(self.get_ne_ip(0),slot))
                    rtn_list.append("false")
                    continue
                else:
                    cpldbig_value = rtn_str.group()[2:]
                    self.info_show(self.log_node_operation, self.log_register_value_success%(self.get_ne_ip(0),slot,4,int(cpldbig_value)))
                
                rtn = self.tnxxx.send_rtn_str("*(0xa0000000+0x5*4)&0xff", self.get_ne_ip(0), slot, DEV_PORT)                       
                rtn_str = None
                rtn_str = re.search(r'= \d+',rtn)
                if None == rtn_str:
                    self.info_show(self.log_node_fail, self.log_connect_slot_fail%(self.get_ne_ip(0),slot))
                    rtn_list.append("false")
                    continue
                else:
                    cpldsmall_value = rtn_str.group()[2:]
                    self.info_show(self.log_node_operation, self.log_register_value_success%(self.get_ne_ip(0),slot,5,int(cpldsmall_value)))
                
                    
                if int(cpldbig_value) == 0x11 and int(cpldsmall_value) == 0x1:
                    self.info_show(self.log_node_success, self.log_cpld_upgrade_success%(self.get_ne_ip(0),slot))  
                else:
                    self.info_show(self.log_node_fail, self.log_cpld_upgrade_fail%(self.get_ne_ip(0),slot))
                    rtn_list.append("false")
                """
                
        return rtn_list
    
    def bsp_jtag_download_cpld_file(self, put_file_list, slot_list):
        """
        put_file_list = [put_file(list),...]
        put_file = [dst_dir, src_dir, src_name]
            dst_dir(str)    --目的目录
            src_dir(str)    --源目录
            src_name(str)   --文件名, 包括"(\d+)或者([\da-f]+)"的表示最新版本
        """
        if list != type(put_file_list):
            self.logger.error(str(line())+" put_files : param type error")
            return False
        """
        #检查本地文件是否存在
        if not self._parse_local_file(put_file_list):
            return False
        """
        #write CPLD
        for put_file in put_file_list:
            if [] != self._bsp_jtag_download_cpld_file(put_file[0], put_file[1], put_file[2], slot_list):
                return False            
        return True
    
    #烧写BIOS的函数针对OPCA
    def _bsp_download_bios_file(self, dst_dir, src_dir, file_name, slot_list, active_opca_slot):
        for slot in slot_list:
            #这里slot_list最好就是一个，分多次调用这个函数，上层先烧standby再烧active
            #1、烧写activeBIOS
            
            if(self.bios == "True"):
                cmd = r'taskSpawn "updatebios",240,0x01000000,20*1024,bsp_flash_bios_download,"%s"' % (dst_dir + r'/'+file_name) 
                #cmd = r'bsp_flash_bios_download "%s"' % (dst_dir + file_name)
                rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), slot, DEV_PORT)
                time.sleep(180)
            
            
            #检查是否成功烧写
            """
            if [] == re.findall(r'success', rtn,0):
                self.info_show(self.log_node_fail, self.log_bios_upgrade_fail%(self.get_ne_ip(0),slot))
            else:
                self.info_show(self.log_node_success, self.log_bios_upgrade_success%(self.get_ne_ip(0),slot))
            """
            
            #2、恢复系统目录
            cmd = r'chkdsk "/tffs",2,0xff00'
            rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), slot, DEV_PORT)

            cmd = r'chkdsk "/fs2",2,0xff00'
            rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), slot, DEV_PORT)
            
            cmd = r'WhichSysXActiveNow'
            rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), slot, DEV_PORT)
            cursys = int(re.findall(r'= (\d) =', rtn,0)[0])
            
            if cursys == 1:
                setsys = 2
            else:
                setsys = 1
                
            #3、设置第一启动目录为backsys
            cmd = r'SetFirstActiveSys %d, "%s"' % (setsys, dst_dir)
            rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), slot, DEV_PORT)
            
            cmd = r'WhichSysXActiveNext'
            rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), slot, DEV_PORT)
            nextsys = int(re.findall(r'= (\d) =', rtn,0)[0])
            
            if setsys == nextsys:
                self.info_show(self.log_node_success, self.log_sys_set_success%(self.get_ne_ip(0),slot))
            else:
                self.info_show(self.log_node_fail, self.log_sys_set_fail%(self.get_ne_ip(0),slot))
            #4、如果是主烧写bios需要保存下配置
            if slot == active_opca_slot:
                cmd  = r'configure terminal'
                rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), 0, CLI_PORT)
                cmd  = r'copy running-config startup-config'
                rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), 0, CLI_PORT)
                cmd  = r'exit'
                rtn = self.tnxxx.send_rtn_str(cmd , self.get_ne_ip(0), 0, CLI_PORT)
        return True
            
    def bsp_download_bios_file(self, put_file_list, slot_list, active_opca_slot):
        """
        put_file_list = [put_file(list),...]
        put_file = [dst_dir, src_dir, src_name]
            dst_dir(str)    --目的目录
            src_dir(str)    --源目录
            src_name(str)   --文件名, 包括"(\d+)或者([\da-f]+)"的表示最新版本
        """   
        if list != type(put_file_list):
            self.logger.error(str(line())+" put_files : param type error")
            return False
        """
        #检查本地文件是否存在
        if not self._parse_local_file(put_file_list):
            return False
        """
        #write bios
        for put_file in put_file_list:
            if not self._bsp_download_bios_file(put_file[0], put_file[1], put_file[2], slot_list, active_opca_slot):
                return False            
        return True       
    
    #############################################################################################
    #                                                                                           #
    #                                    FTP传送文件到OPCA & POS                                #
    #                                                                                           #
    #############################################################################################
    #先删除两个备用目录上面的文件
    def del_old_files_opca(self, upgrade_file_dic, upgrade_slot_dic):
        for card_type,slot_list in upgrade_slot_dic.items():
            #进行校验
            if str != type(card_type) or \
               list != type(slot_list):
                self.logger.error(str(line())+" delete_files : data type error <%s>"%(str((card_type,slot_list))))
                return False
            if len(slot_list) <= 0 : continue
            if not upgrade_file_dic.has_key(card_type):
                self.logger.error(str(line())+" delete_files : card_type not suppost <%s>"%(card_type))
                return False
            
            active_opca_slot = self.slot_backupsys_list[0][0]
            
            for slot in slot_list:
                if slot == active_opca_slot:
                    boot_dir = self.slot_backupsys_list[0][1]
                    if self.delete_files([[boot_dir, ".+"]], slot):
                        self.info_show(self.log_node_success, "Delete Active Opca Slot:%d, backsys(%s)'file!----success\n" % (slot, boot_dir))
                    else:
                        self.info_show(self.log_node_fail, "Delete Active Opca Slot:%d, backsys(%s)'file!----fail\n"% (slot, boot_dir))
                        return False
                else:
                    boot_dir = self.slot_backupsys_list[1][1]
                    if self.delete_files([[boot_dir, ".+"]], slot):
                        self.info_show(self.log_node_success, "Delete Standby Opca Slot:%d, backsys(%s)'file!----success\n"% (slot, boot_dir))
                    else:
                        self.info_show(self.log_node_fail, "Delete Standby Opca Slot:%d, backsys(%s)'file!----fail\n"% (slot, boot_dir))
                        return False
                    
        return True
    
    #给OPCA升级文件用到的函数    
    def upgrade_files_opca(self, upgrade_file_dic, upgrade_slot_dic):
        """
        upgrade_file_dic = {card_type:upgrade_file_list, ...}
            card_type(str)          --单板类型
            upgrade_file_list = [dst_dir, dst_file, src_dir, src_file]
                dst_dir(str)        --目的目录
                dst_file(str)       --目的文件名
                src_dir(str)        --源目录
                src_file(str)       --源文件名
                
        upgrade_slot_dic = {card_type:slot_list, ...}
            card_type(str)      --单板类型
            slot_list = [slot, ...]
                slot(int)       --槽位号
        opca的系统目录可以是/tffs/sys/ 或者 /fs2/sys/
        """
        #card_type="OPCA", slot_list=[3,4]
        for card_type,slot_list in upgrade_slot_dic.items():
            #进行校验
            if str != type(card_type) or \
               list != type(slot_list):
                self.logger.error(str(line())+" upgrade_files : data type error <%s>"%(str((card_type,slot_list))))
                return False
            if len(slot_list) <= 0 : continue
            if not upgrade_file_dic.has_key(card_type):
                self.logger.error(str(line())+" upgrade_files : card_type not suppost <%s>"%(card_type))
                return False                      
            
            active_opca_slot = self.slot_backupsys_list[0][0]
            
            for slot in slot_list:
                put_file_list = []
                
                if slot == active_opca_slot:
                    boot_dir = self.slot_backupsys_list[0][1]
                    self.info_show(self.log_node_success, "Put Active Opca Slot:%d, backsy(%s)s'file!\n" % (slot, boot_dir))
                else:
                    boot_dir = self.slot_backupsys_list[1][1]
                    self.info_show(self.log_node_success, "Put Standby Opca Slot:%d, backsys(%s)'file!\n" % (slot, boot_dir))
                    
                for upgrade_file in upgrade_file_dic[card_type]:                    
                    put_file_list.append([boot_dir, deepcopy(upgrade_file[2]), deepcopy(upgrade_file[3])])                    
                
                #删除单独列出来
                """
                if not self.delete_files([[boot_dir, ".+"]], slot):
                    return False              
                """
                
                put_slot_list = []
                put_slot_list.append(slot)
                
                if not self.put_files(put_file_list, put_slot_list, active_opca_slot):
                    return False
                
                if "True" == self.md5:
                    upgrade_txt_file=put_file_list[0][1]+'/'+put_file_list[0][2]
                    md5_file_list = deepcopy(put_file_list)
                    md5_list=open(upgrade_txt_file)                    

                    #提取文件名和md5
                    for each_line in md5_list:                        
                        md5_field=re.findall('\]\[.+]',each_line)
                        filename_field=re.findall('\[.+\]\[',each_line)
                        md5=md5_field[0][2:len(md5_field[0])-1]
                        filename=filename_field[0][1:len(filename_field[0])-2]
                        found = False
                        #添加md5信息
                        for i,each_put_file in enumerate(md5_file_list):
                            if None != re.search(each_put_file[2],filename):
                                md5_file_list[i].append(md5)
                                md5_file_list[i][2]=filename
                                found = True                                
                                break
                        if False == found:
                            self.info_show(self.log_node_fail, self.log_md5_fail%(self.get_ne_ip(0),slot,filename))
                            md5_list.close
                            return False
                            
                    #删除upgrade.txt,此文件没有md5值.
                    md5_file_list.remove(md5_file_list[0])
                    #删除filelist.txt,此文件没有md5值.
                    md5_file_list.pop()
                    
                    #目前先单独添加CLPD和BIOS的MD5
                    for  i, md5_info in enumerate(md5_file_list):
                        if md5_info[2] == self.bios_name:
                            md5_file_list[i].append(self.md5_list[0])
                        if md5_info[2] == self.cpld_name:
                            md5_file_list[i].append(self.md5_list[1])
                            
                    if not self.md5_files(md5_file_list, put_slot_list, active_opca_slot):
                        return False
                self.info_show(self.log_node_success, self.log_put_opca_success%(self.get_ne_ip(0),slot))            
        return True
    
    #给POS板升级文件用到的函数
    def upgrade_files_pos(self, upgrade_file_dic, upgrade_slot_dic, masterppc):
        """
        upgrade_file_dic = {card_type:upgrade_file_list, ...}
            card_type(str)          --单板类型
            upgrade_file_list = [dst_dir, dst_file, src_dir, src_file]
                dst_dir(str)        --目的目录
                dst_file(str)       --目的文件名
                src_dir(str)        --源目录
                src_file(str)       --源文件名
                
        upgrade_slot_dic = {card_type:slot_list, ...}
            card_type(str)      --单板类型
            slot_list = [slot, ...]
                slot(int)       --槽位号
        
        pos的系统目录可以是/tffs/sys/
        """ 
                    
        for card_type,slot_list in upgrade_slot_dic.items():
            #进行校验
            if str != type(card_type) or \
               list != type(slot_list):
                self.logger.error(str(line())+" upgrade_files : data type error <%s>"%(str((card_type,slot_list))))
                return False
            if len(slot_list) <= 0 : continue
            if not upgrade_file_dic.has_key("N64F01") or not upgrade_file_dic.has_key("N16F01"):
                self.logger.error(str(line())+" upgrade_files : card_type not suppost <%s>"%(card_type))
                return False
            
            #这个是POS板不需要添加OPCA的槽位
            #slot_list.insert(0,masterppc)
            put_file_list = []
            
            for upgrade_file in upgrade_file_dic["N64F01"]:                    
                put_file_list.append([tffs_dir, deepcopy(upgrade_file[2]), deepcopy(upgrade_file[3])])
            
            """
            #添加N16的槽位    
            for upgrade_file in upgrade_file_dic["N16F01"]:                    
                put_file_list.append([tffs_dir, deepcopy(upgrade_file[2]), deepcopy(upgrade_file[3])])
            """
            
            if not self.put_files(put_file_list, slot_list, masterppc):
                self.info_show(self.log_node_fail, self.log_put_pos_fail%(self.get_ne_ip(0)))
                return False
            else:
                self.info_show(self.log_node_success, self.log_put_pos_success%(self.get_ne_ip(0)))
                
        return True
    
     ################################################################################################
    #                                                                                               #
    # 最后的版本号终极校验CPLD\BIOS\SW，返回字典为空代表升级成功,因为该字典记录需要升级的内容       #
    #                                                                                               #
    ################################################################################################
    
    def check_version(self, upgrade_slot_pos_dic):
        upgrade_info_dic = {}
        #such as ..{“CPLD”：cpld_list, "BIOS":bios_list, "SoftWare": software_list}
        
        cpld_upgrade_list = []
        bios_upgrade_list = []
        software_upgrade_list = []
        
        cmd = r'show version'
        #给主控板发命令
        rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), 0, CLI_PORT) 
        
        #需要得到槽位号，以及该槽位下的BIOS、CPLD、software版本号因为BIOS和CPLD的升级需要烧写
        #得到形式如下的列表
        #CPLD-5,6,7,8 pos
        #BIOS-3,4 opca
        #SW-3,4,5,6,7,8
    
        cpld_version = re.findall(r"slot:\s+(\d+)\s+(?:--More--\s+)?desp:\s+\w+\s+\w+\s+(?:--More--\s+)?version:\s+.+{CPLD:(\w+\.+\w+\.+\w+\.+\w)}+.+\s+", rtn_str, re.I)
        bios_version = re.findall(r"slot:\s+(\d+)\s+(?:--More--\s+)?desp:\s+\w+\s+\w+\s+(?:--More--\s+)?version:\s+.+{BIOS:(\w+\.+\w+\.+\w+\.+\w)}+.+\s+", rtn_str, re.I)
        software_version = re.findall(r"slot:\s+(\d+)\s+(?:--More--\s+)?desp:\s+\w+\s+\w+\s+(?:--More--\s+)?version:\s+.+{.+release (\w+\.+\w+\.+\w+\.+\w+).+}+.+", rtn_str, re.I)
         
        for version in cpld_version:
            #检查cpld版本号是否需要升级
            if [] == version:
                continue
            else:
                #检查这个POS槽位是否需要升级才作比较
                if int(version[0]) in  upgrade_slot_pos_dic["N64F01"]:
                    #检查版本是否升级,直接比较字符串，新版本号大于旧版本号
                    if self.cpld_version_dict.get(version[0]) == version[1]:
                        self.info_show(self.log_node_success, self.log_check_version %(self.get_ne_ip(0),version[0],"CPLD",version[1], self.cpld_version_dict[version[0]], "Success"))                        
                    else:
                        #记录本次不需要升级操作
                        self.info_show(self.log_node_fail, self.log_check_version %(self.get_ne_ip(0),version[0],"CPLD",version[1], self.cpld_version_dict[version[0]], "Fail"))
                        #将槽位添加到升级列表中
                        cpld_upgrade_list.append(version[0])
        for version in bios_version:
            #检查bios版本号是否需要升级
            if [] == version:
                continue
            else:
                #检查版本是否升级,直接比较字符串，新版本号大于旧版本号
                if self.bios_version_dict.get(version[0]) == version[1]:
                    self.info_show(self.log_node_success, self.log_check_version %(self.get_ne_ip(0),version[0],"BIOS",version[1], self.bios_version_dict[version[0]], "Success"))                   
                else:
                    #记录本次不需要升级操作
                    self.info_show(self.log_node_fail, self.log_check_version %(self.get_ne_ip(0),version[0],"BIOS",version[1], self.bios_version_dict[version[0]], "Fail"))
                    #将槽位添加到升级列表中
                    bios_upgrade_list.append(version[0])
        for version in software_version:
            #检查software版本号是否需要升级
            if [] == version:
                continue
            else:
                #检查版本是否升级,直接比较字符串，新版本号大于旧版本号
                if self.software_version_dict.get(version[0]) == version[1]:
                    self.info_show(self.log_node_success, self.log_check_version %(self.get_ne_ip(0),version[0],"SoftWare",version[1], self.software_version_dict[version[0]], "Success"))                    
                else:
                    #记录本次不需要升级操作
                    self.info_show(self.log_node_fail, self.log_check_version %(self.get_ne_ip(0),version[0],"SoftWare",version[1], self.software_version_dict[version[0]], "Fail"))
                    #将槽位添加到升级列表中
                    software_upgrade_list.append(version[0])
                    
        #将CPLD、BIOS、SoftWare组合成字典返回
        if [] != cpld_upgrade_list:
            upgrade_info_dic["CPLD"] = cpld_upgrade_list
        if [] != bios_upgrade_list:
            upgrade_info_dic["BIOS"] = bios_upgrade_list
        if [] != software_upgrade_list:
            upgrade_info_dic["SoftWare"] = software_upgrade_list
        
        return upgrade_info_dic

    def check_version_new(self):
        
        #有版本校验的槽位
        slot_version_list = [1,2,3,4,5,6,7,8]
        #单板硬件软件版本解析的正则表达式
        card_re_dic = {
        "CM48E16":(r"{PCB:(\w+)}{CPLD:\w(\d+.+\d+)}{FPGA1:\w(\d+.+\d+)}{FPGA2:\w(\d+.+\d+)}",""),
        "CM48E16S":(r"{PCB:(\w+)}{CPLD:\w(\d+.+\d+)}{FPGA1:\w(\d+.+\d+)}{FPGA2:\w(\d+.+\d+)}",""),
        "CGF12":(r"{PCB:(\w+)}{CPLD:\w(\d+.+\d+)}",""),
        "CGF12S":(r"{PCB:(\w+)}{CPLD:\w(\d+.+\d+)}",""),
        "OPCA":(r"{PCB:(\w+)}{CPLD:\w(\d+.+\d+)}{FPGA:\w(\d+.+\d+)}",r"{BIOS:\w(\d+.+\d+)}{BSP:\w(\d+.+\d+)}{.+release \w(\d+\.+\w+\.+\w+\.+\w+).+"),
        "N64F01":(r"{PCB:(\w+)}{CPLD:\w(\d+.+\d+)}{FPGA:\w(\d+.+\d+)}",r"{BIOS:\w(\d+.+\d+)}{BSP:\w(\d+.+\d+)}{.+release \w(\d+\.+\w+\.+\w+\.+\w+).+"),
        "N64F01(C0)":(r"{PCB:(\w+)}{CPLD:\w(\d+.+\d+)}{FPGA:\w(\d+.+\d+)}",r"{BIOS:\w(\d+.+\d+)}{BSP:\w(\d+.+\d+)}{.+release \w(\d+\.+\w+\.+\w+\.+\w+).+"),
        "N16F01":(r"{PCB:(\w+)}{CPLD:\w(\d+.+\d+)}{FPGA:\w(\d+.+\d+)}",r"{BIOS:\w(\d+.+\d+)}{BSP:\w(\d+.+\d+)}{.+release \w(\d+\.+\w+\.+\w+\.+\w+).+"),
        "NXGF01":(r"{PCB:(\w+)}{CPLD:\w(\d.+\d+)}",""),
        "NXGF01S":(r"{PCB:(\w+)}{CPLD:\w(\d.+\d+)}",""),
        }
                
        cmd = r'show version'
        #给主控板发命令
        rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), 0, CLI_PORT)
        
        #解析出slot、soft/hard、version
        slot_desp_version_list = re.findall(r"slot:\s+(\d+)+\s+(?:--More--\s+)?desp:\s+(\w+)\s\w+\s+(?:--More--\s+)?version:\s+(.+)", rtn_str, re.I)
        
        #分别校验每一条记录
        for slot_desp_version in slot_desp_version_list:
            if int(slot_desp_version[0]) in slot_version_list:
                #查询单板类型
                cmd = r'show card %d' % int(slot_desp_version[0])
                #给主控板发命令
                rtn_str = self.tnxxx.send_rtn_str(cmd, self.get_ne_ip(0), 0, CLI_PORT)
                card_type = re.findall(r"Card:\s+(\w+)\s*\n*", rtn_str, re.I)
    
                if slot_desp_version[1]  == "hard":
                    version = re.findall(card_re_dic[card_type[0].upper()][0],slot_desp_version[2])
                    #第0位置是PCB
                    for i in range(0, len(version[0]) - 1):
                        #如果是C0板子，需要改变一下单板名字
                        if int(slot_desp_version[0]) in self.upgrade_slot_pos_c0_dic["N64F01"] + self.upgrade_slot_pos_c0_dic["N16F01"]:
                            card_type = ["N64F01(C0)"]
                        #CPLD校验特殊，是个列表
                        if 0 == i:
                            #log_check_version_fail = "Slot:%s Card:%s check version %s current version:%s dest version:%s fail!\n"
                            if  version[0][i+1] not in self.card_version_dic[card_type[0].upper()][0][i]:
                                print log_check_version_fail % (int(slot_desp_version[0]), card_type[0].upper(),version_hard_dic[i], version[0][i+1],self.card_version_dic[card_type[0].upper()][0][i])
                                self.info_show(self.log_node_fail, log_check_version_fail % (int(slot_desp_version[0]), card_type[0].upper(),version_hard_dic[i], version[0][i+1],self.card_version_dic[card_type[0].upper()][0][i]))
                                return False
                            else:
                                print log_check_version_success % (int(slot_desp_version[0]), card_type[0].upper(),version_hard_dic[i], version[0][i+1],self.card_version_dic[card_type[0].upper()][0][i])
                                self.info_show(self.log_node_success,  log_check_version_success % (int(slot_desp_version[0]), card_type[0].upper(),version_hard_dic[i], version[0][i+1],self.card_version_dic[card_type[0].upper()][0][i]))
                        else:
                            if  version[0][i+1] != self.card_version_dic[card_type[0].upper()][0][i]:
                                print log_check_version_fail % (int(slot_desp_version[0]), card_type[0].upper(),version_hard_dic[i], version[0][i+1],self.card_version_dic[card_type[0].upper()][0][i])
                                self.info_show(self.log_node_fail, log_check_version_fail % (int(slot_desp_version[0]), card_type[0].upper(),version_hard_dic[i], version[0][i+1],self.card_version_dic[card_type[0].upper()][0][i]))
                                return False
                            else:
                                print log_check_version_success % (int(slot_desp_version[0]), card_type[0].upper(),version_hard_dic[i], version[0][i+1],self.card_version_dic[card_type[0].upper()][0][i])
                                self.info_show(self.log_node_success,  log_check_version_success % (int(slot_desp_version[0]), card_type[0].upper(),version_hard_dic[i], version[0][i+1],self.card_version_dic[card_type[0].upper()][0][i]))
                else:
                    version = re.findall(card_re_dic[card_type[0].upper()][1],slot_desp_version[2])
                    for i in range(0, len(version[0])):
                        #如果是C0板子，需要改变一下单板名字
                        if int(slot_desp_version[0]) in self.upgrade_slot_pos_c0_dic["N64F01"] + self.upgrade_slot_pos_c0_dic["N16F01"]:
                            card_type = ["N64F01(C0)"]
                            
                        if  version[0][i] != self.card_version_dic[card_type[0].upper()][1][i]:
                            print log_check_version_fail % (int(slot_desp_version[0]), card_type[0].upper(),version_soft_dic[i], version[0][i],self.card_version_dic[card_type[0].upper()][1][i])
                            self.info_show(self.log_node_fail, log_check_version_fail % (int(slot_desp_version[0]), card_type[0].upper(),version_soft_dic[i], version[0][i],self.card_version_dic[card_type[0].upper()][1][i]))
                            return False
                        else:
                            print log_check_version_success % (int(slot_desp_version[0]), card_type[0].upper(),version_soft_dic[i], version[0][i],self.card_version_dic[card_type[0].upper()][1][i])
                            self.info_show(self.log_node_success,  log_check_version_success % (int(slot_desp_version[0]), card_type[0].upper(),version_soft_dic[i], version[0][i],self.card_version_dic[card_type[0].upper()][1][i]))
        return True          

        
if __name__ == "__main__":
    case = UpgradeSoftware()
    case.execute()